#include <queue>
#include "lockGuard.hpp"

#define QUEUESIZE 5 // 队列大小

template <class T> // 任务类型
class BlockQueue
{
public:
    BlockQueue()
        : _capacity(QUEUESIZE)
    {
        // 初始化条件变量和互斥锁
        pthread_mutex_init(&_mtx, nullptr);
        pthread_cond_init(&_isEmpty, nullptr);
        pthread_cond_init(&_isFull, nullptr);
    }

    ~BlockQueue()
    {
        // 销毁条件变量和互斥锁
        pthread_mutex_destroy(&_mtx);
        pthread_cond_destroy(&_isEmpty);
        pthread_cond_destroy(&_isFull);
    }

    // 生产者向队列插入任务
    void push(const T &t)
    {
        lockGuard lockguard(&_mtx); // 智能锁
        // 先判断队列是否为满
        while (_q.size() == _capacity)
        {
            // 队列满，一直等待
            // pthread_mutex_lock(&_mtx);
            pthread_cond_wait(&_isFull, &_mtx);
        }
        _q.push(t);

        pthread_cond_signal(&_isEmpty); // 唤醒消费者
        // pthread_mutex_unlock(&_mtx);
    }

    // 消费者向队列获取任务
    void pop(T *t)
    {
        // 队列为空则等待
        lockGuard lockguard(&_mtx); // 智能锁
        while (_q.size() == 0)
        {
            // pthread_mutex_lock(&_mtx);
            pthread_cond_wait(&_isEmpty, &_mtx);
        }
        *t = _q.front();
        _q.pop();
        pthread_cond_signal(&_isFull);
        // pthread_mutex_unlock(&_mtx);
    }

private:
    std::queue<T> _q;        // 队列
    int _capacity;           // 队列容量
    pthread_mutex_t _mtx;    // 队列互斥锁
    pthread_cond_t _isFull;  // 队列是否为满
    pthread_cond_t _isEmpty; // 队列是否为空
};